package com.dark.shiro.realm;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import com.dark.common.web.validate.AjaxResponse;
import com.dark.sys.service.AuthService;
import com.dark.sys.service.ResourceService;
import com.dark.sys.service.RoleService;
import com.dark.sys.service.UserService;
import com.dark.sys.web.dto.AuthDto;
import com.dark.sys.web.dto.ResourceDto;
import com.dark.sys.web.dto.RoleDto;
import com.dark.sys.web.dto.UserDto;

public class UserRealm extends AuthorizingRealm {
	
	@Autowired
	private UserService userService ;
	
	@Autowired
	public AuthService authService ;
	
	@Autowired
	private RoleService roleService ;
	
	@Autowired
	private ResourceService resourceService ;
	

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		List<String> roles = new ArrayList<String>();   
		List<String> permissions = new ArrayList<String>();
		String username = (String) super.getAvailablePrincipal(principals) ;
		
		System.out.println("=====>获取用户["+username+"]角色和权限");
		
		UserDto user = this.userService.getByUsername(username) ;
		
		AuthDto auth = this.authService.getByUserId(user.getId()) ;
		
		if(null != auth) {
			Set<Integer> resourceIds = new HashSet<Integer>() ;
			
			List<RoleDto> role = this.roleService.getByRoleIds(auth.getRoleIds()) ;
			
			//获取角色
			for (RoleDto r : role) {
				roles.add(r.getIdentity()) ;
				//获取角色对应的操作资源ID
				if(null != r.getResourceIds()) {
					String[] split = r.getResourceIds().split(",") ;
					for (String id : split) {
						resourceIds.add(Integer.parseInt(id)) ;
					}
				}
			}
			
			//获取操作资源
			if(!resourceIds.isEmpty()) {
				List<ResourceDto> resourceOperations = this.resourceService.getResourceOperations(StringUtils.join(resourceIds, ",")) ;
				for (ResourceDto resOper : resourceOperations) {
					String identity = resOper.getParentIdentity() + ":" + resOper.getIdentity() ;
					permissions.add(identity);
				}
			}
		}
		
		
		//为当前用户设置角色和权限  
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();  
		info.addRoles(roles);  
		info.addStringPermissions(permissions);  
		         
		return info;  
	}

	/**
	 * 验证用户登录
	 * @param token
	 * @return
	 * @throws AuthenticationException
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		//System.out.println("验证当前Subject时获取到token为：" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));  
		
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		String username = upToken.getUsername().trim();
        String password = "";
        if (upToken.getPassword() != null) {
            password = new String(upToken.getPassword());
        }
        UserDto user = null ;
        
		try {
			
			AjaxResponse ajaxResp = this.userService.validateLogin(username, password) ;
			user = (UserDto) ajaxResp.getObj() ;
			
		} catch(UnknownAccountException uae){  
            throw uae ;
        } catch(IncorrectCredentialsException lae){  
            throw lae ;
        } 
		
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user.getUsername(), password, getName()) ;
		return info ;
	}
	
	
	@Override
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }

    @Override
    public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        super.clearCachedAuthenticationInfo(principals);
    }

    @Override
    public void clearCache(PrincipalCollection principals) {
        super.clearCache(principals);
    }

    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }

    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }

}
